#coding:utf-8

import os
from datetime import datetime
import json

from flask import Flask
from flask import render_template, request, g, redirect, url_for, session, abort
from flask.ext.login import LoginManager, login_required, login_user, logout_user, current_user

from models import *
from forms import *
from filter import *
from sqlalchemy.sql import and_, or_
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import joinedload
from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
from config import APK_PATH
import hashlib
#print APK_PATH

from init_db import db_session

app = Flask(__name__)
app.secret_key = 'al+lfjoij1243r7qw9asdf8a@WYHdu!(@*'

app.jinja_env.filters['filter_usertype'] = filter_usertype

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"



@login_manager.user_loader
def load_user(user_id):
    return User.query.filter(User.id == user_id).one()


@app.route('/login/', methods=['GET', 'POST',])
def login():
    if request.method == 'POST':
        form = LoginForm(request.form)
        print form.validate()
        if form.validate():
            email = form.email.data
            password = hashlib.md5(form.password.data).hexdigest()
            try:
                user = User.query.filter(User.email == email, User.passwd == password).one()
            except NoResultFound, e:
                return redirect('/login/?error=1')
            login_user(user)
        return redirect(request.args.get('next') or '/')
    elif request.method == 'GET':
        error = request.args.get('error', None)
    return render_template('/opda/login.html', **locals())

@app.route('/logout/')
def logout():
    logout_user()
    return redirect('/')

@app.route('/signup/')
def signup():
    if request.method == 'POST':
        form = SignupForm(request.form)
        #if form.validate():
        #    user = User(form.email.data, form.passwd.data)
        #    db_session.add(user)
        #    db_session.commit()
    return render_template('signup.html')

@app.route('/')
@login_required
def index():
    return render_template('/opda/index.html', **locals())
    # if current_user.user_type in [User.USER_MSO, User.USER_MSO_VISITOR]:
    #     return redirect('/app/')
    # if current_user.user_type == User.USER_BOX or current_user.super_user:
    #     return redirect('/box/')
    # return render_template('/opda/index.html', **locals())

@app.route('/box/', methods=['GET', 'POST'])
@login_required
def box():
    if request.method == 'GET':
        if current_user.super_user:
            boxs = Box.query.all()
        else:
            boxs = Box.query.filter(Box.user_id == current_user.id).limit(5).all()
    else:
        pass
    return render_template('/opda/box.html', **locals())

@app.route('/boxautoadd/', methods=['GET'])
def box_auto_add():
    if request.method == 'GET':
        mac = request.args.get('mac', None)
        cpuid = request.args.get('cpuid', None)
        pwd = request.args.get('pwd', None)
        info = request.args.get('info', None)
        if pwd == '2wsx1qaz':
            boxs = Box.query.filter(Box.mac == mac).all()
            if len(boxs) == 1:
                return 'success'
            elif len(boxs) == 0:
                box = Box()
                box.mac = mac
                box.cpu_id = cpuid
                box.info = info
                box.user_id = 1
                db_session.add(box)
                db_session.commit()
                return 'success'
        else:
            return 'false'
    return 'success'
    
    
@app.route('/box/setup', methods=['POST'])
def box_setup():
    if request.method == 'POST':
        upstr = request.form.get('json')
        data = json.loads(upstr)
        mac = data.get('mac')
        dv = data.get('device')
        box = Box.query.filter(Box.mac == mac).one()
        box.last_upload = datetime.now()
        device = BoxDevice()
        device.box_id = box.id
        device.dv_release = dv.get('release')
        device.dv_imei = dv.get('imei')
        device.dv_imei2 = dv.get('imei2')
        device.dv_vendor = dv.get('vendor')
        device.dv_sn = dv.get('sn')
        device.dv_wifimac = dv.get('wifimac')
        device.dv_brand = dv.get('brand')
        device.dv_model = dv.get('model')
        device.dv_sdk = dv.get('sdk')
        db_session.add(device)
        db_session.commit()
    return '{"code":200}'



@app.route('/boxinfo/<int:box_id>')
@login_required
def boxinfo(box_id):
    if current_user.super_user:
        box = Box.query.filter(Box.id == box_id).one()
        user_package = Package.query
    else:
        box = Box.query.filter(Box.id == box_id, Box.user_id == current_user.id).one()
        user_package = Package.query.filter(Package.uploader_id == current_user.id)
    box_package = BoxPackage.query.filter(BoxPackage.box_id == box_id).all()
    box_package_id_list = [b.package_id for b in box_package]
    used_package = Package.query.filter(Package.id.in_(box_package_id_list)).all()
    no_used_package = user_package.filter(~Package.id.in_(box_package_id_list)).all()
    return render_template('/opda/boxinfo.html', **locals())


@app.route('/boxdev/<int:box_id>')
@login_required
def boxdev(box_id):
    if current_user.super_user:
        box = Box.query.filter(Box.id == box_id).one()
    else:
        box = Box.query.filter(Box.id == box_id, Box.user_id == current_user.id).one()
    box_device = BoxDevice.query.filter(BoxDevice.box_id == box.id).all()

    return render_template('/opda/boxdevice.html', **locals())



@app.route('/app/', methods=['GET', 'POST'])
@login_required
def app_mso():
    if request.method == 'GET':
        if current_user.user_type == User.USER_MSO_VISITOR:
            app_mso = App.query.filter(or_(App.visitor == current_user.id, App.visitor == 0)).all()
        else:
            users = User.query.filter(User.user_type == User.USER_MSO_VISITOR).all()
            app_mso = App.query.all()
        return render_template('/opda/app.html', **locals())
    else:
        form = AddAppForm(request.form)
        if form.validate():
            app_mso = App()
            app_mso.name = form.app_name.data
            app_mso.visitor = form.visitor.data
            db_session.add(app_mso)
            db_session.commit()
        else:
            return str(form.errors)
        return redirect('/app/')

@app.route('/appactive/<int:app_id>', methods=['GET', 'POST'])
@login_required
def app_active(app_id):
    if request.method == 'GET':
        app_mso = App.query.filter(App.id == app_id).one()
        app_active = AppActive.query.filter(AppActive.app_id == app_id).all()
        return render_template('/opda/appactive.html', **locals())
    else:
        form = AppActiveForm(request.form)
        if form.validate():
            app_active = AppActive()
            app_active.app_id = app_id
            app_active.record_time = form.time.data
            app_active.active_amount = form.amount.data
            app_active.add_time = datetime.now()
            db_session.add(app_active)
            db_session.commit()
        else:
            return str(form.errors)
        return redirect('/appactive/%s' % app_id)


@app.route('/appactivedel/<int:appactive_id>', methods=['GET'])
@login_required
def app_active_del(appactive_id):
    app_active = AppActive.query.filter(AppActive.id == appactive_id).one()
    db_session.delete(app_active)
    db_session.commit()
    return redirect('/appactive/%s' % app_active.app_id)


@app.route('/upload/apk/', methods=['POST'])
@login_required
def upload():
    f = request.files['package']
    name = request.form.get('name', None)
    print (name, )
    info = request.form.get('info', None)
    if name:
        file_content = f.stream.read()
        safe_file_name = hashlib.md5(f.filename).hexdigest()
        with open(os.path.join(APK_PATH , safe_file_name), 'wb') as fp:
            fp.write(file_content)
        package = Package()
        package.name = name
        package.file_name = f.filename
        package.uploader_id = current_user.id
        package.url = safe_file_name
        package.md5 = hashlib.md5(file_content).hexdigest()
        package.update_time = datetime.now()
        package.size = len(file_content)
        package.info = info
        db_session.add(package)
        db_session.commit()
    return redirect('/package/')



@app.route('/user/', methods=['GET', 'POST'])
@login_required
def user():
    if request.method == 'GET':
        if current_user.super_user:
            user = User.query.all()
            return render_template('/opda/user.html', **locals())
        else:
            abort(404)
    else:
        form = AddUserForm(request.form)
        if form.validate():
            email = form.user_email.data
            user_name = form.user_name.data
            user_type = form.user_type.data
            user = User(user_name, email)
            user.user_type = user_type
            user.passwd = '1bbd886460827015e5d605ed44252251'
            db_session.add(user)
            db_session.commit()
        else:
            return str(form.errors)
        return redirect('/user/')

@app.route('/userdel/<int:user_id>')
@login_required
def user_del(user_id):
    if current_user.super_user:
        user = User.query.filter(User.id == user_id).one()
        db_session.delete(user)
        db_session.commit()
        return redirect('/user/')
    else:
        abort(404)

@app.route('/userinfo/<int:user_id>')
@login_required
def user_info(user_id):
    if current_user.super_user:
        user = User.query.filter(User.id == user_id).one()
        box = Box.query.filter(Box.user_id == user_id).all()
        return render_template('/opda/user_info.html', **locals())
    else:
        abort(404)
@app.route('/package/')
@login_required
def package():
    print current_user.id
    print '*'*20, db_session
    if current_user.super_user:
        package = Package.query.all()
    else:
        package = Package.query.filter(Package.uploader_id == current_user.id).all()
    return render_template('/opda/package.html', **locals())

@app.route('/addpackage/<int:box_id>/<int:package_id>')
@login_required
def add_package(box_id, package_id):
    box = Box.query.filter(Box.id == box_id).one()
    if box.user_id != current_user.id and not current_user.super_user:
        abort(404)
    try:
        boxpackage = BoxPackage()
        boxpackage.box_id = box_id
        boxpackage.package_id = package_id
        db_session.add(boxpackage)
        db_session.commit()
    except IntegrityError, e:
        db_session.rollback()
    return redirect('/boxinfo/%s' % box_id)

@app.route('/outpackage/<int:box_id>/<int:package_id>')
@login_required
def out_package(box_id, package_id):
    box = Box.query.filter(Box.id == box_id).one()
    if box.user_id != current_user.id and not current_user.super_user:
        abort(404)
    box_package = BoxPackage.query.filter(BoxPackage.box_id == box_id, BoxPackage.package_id == package_id).one()
    db_session.delete(box_package)
    db_session.commit()
    return redirect('/boxinfo/%s' % box_id)


#盒子fetch view，不需要登录
@app.route('/update', methods=['POST',])
def update_apk():
    req_info = json.loads(request.form.get('json'))
    print req_info
    box_mac = req_info.get('mac', None)
    if box_mac is None:
        abort(404)
    box = Box.query.filter(Box.mac == box_mac).one()
    packages = Package.query.join(BoxPackage, Package.id == BoxPackage.package_id).filter(BoxPackage.box_id==box.id).all()
    items = []
    for p in packages:
        item = {}
        item['location'] = 'system'
        item['protected'] = '1'
        item['show_order'] = '1'
        item['pacakge_name'] = p.md5
        item['download'] = p.url
        item['md5'] = p.md5
        item['title'] = p.md5
        item['filename'] = p.file_name
        items.append(item)
    res = {'item': items, 'code':200}
    return json.dumps(res)

@app.route('/addbox/')
def add_box():
    if current_user.super_user:
        return render_template('opda/add_box.html', **locals())
    return redirect('/')

@app.route('/delpackage/<int:package_id>')
@login_required
def rm_package(package_id):
    if current_user.super_user:
        package = Package.query.filter(Package.id == package_id).one()
    else:
        package = Package.query.filter(Package.id == package_id, Package.uploader_id == current_user.id).one()
    db_session.delete(package)
    db_session.commit()
    return redirect('/package/')


@app.route('/flash/')
def flash():
    db_session.remove()
    return redirect('/')

@app.teardown_appcontext
def shutdown_session(exception=None):
    db_session.remove()


if __name__ == '__main__':
    app.run(debug=True, host="0.0.0.0", port=80)
